-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add textobject for entries/elements of list-like things #8150
Add textobject for entries/elements of list-like things #8150
Conversation
ec1e4f4
to
82728a0
Compare
I had to let this sit a bit longer to gain clarity, and also life got in the way for quite a while. However, I think I've narrowed this down to a sensible implementation and I think its ready for more eyes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation looks fine to me since it's fairly simple.
I think conceptually it seems useful to have a textonject like this.
Will try to test this a bit if the queries make sense to me.
Can you clarify what you mean with that comment avkht class fields? I see rust field declarations are covered by these textobjects which sound just like class fields to me.
@pascalkuthe certainly! Perhaps the best way to explain is to look at some specific examples that don't fit the mold precisely. In JavaScript, there are a number of ways to create objects. One of these is the "object literal" syntax, which looks a lot like a hash table definition in other languages: const person = {
name: 'Ragesh',
age: '52',
}; In this instance, it is easy to say that the const person = {
name: 'Yvette',
age: '33',
speak: () => console.log('Bonjour!')
} Here the Now consider that in recent years JavaScript grew some class-based syntactic sugar to make constructing objects more familiar to those coming from class-based OO languages. We now can express the same object this way: class Person {
constructor(name, age) {
this.name = name
this.age = age
}
speak() {
console.log('你好')
}
}
const person = new Person('Jian', 19) Does it now make sense to be able to jump to the assigments for class Fish {
#numFins = 3
getNumFins() {
return this.#numFins
}
} Initially, my answer was "yes, these should count", but as I tried it in more contexts it just felt kind of inconsistent and awkward to use. Even where you might expect it to act like entries in a data structure there can be awkwardness, for example with a PHP Data Transfer Object pattern: readonly class BlogData
{
public function __construct(
public string $title,
public Status $status,
public ?DateTimeImmutable $publishedAt = null,
) {}
} Here you can see that due to PHP's constructor property promotion (adding visibility to the constructor signature means those arguments immediately become properties on that class with said visibility), we now have an overlap between the definition of the "argument/parameter" textobject we already have and this new "entry/element" textobject. In the specific case of Rust, field definitions on a struct feel to me like they belong, as In other words, getting a useful definition of what does and does not belong is difficult to achieve. I gave it my best shot for the covered languages, given that my experience with many of them is surface level. |
That makes sense to me. I guess you could in theory view every assignment as a key value pair which I definitely wouldn't want the captures to do. Rust is fairly rigorous and I think I agree with the way its defined there and python makes sense too. I don't have enough experience with js/php to really comment on that but your explanation sounds reasonable. |
Co-authored-by: Michael Davis <[email protected]>
Closes #3006
Explanation
This introduces a new tree-sitter textobject query for elements or "entries" of list-like (data structure like) objects. This might be array elements, tuple entries, key-value pairs within object literals, enum members, etc. The "inside" subtype can mean the individual parts of key-value pairs where that is applicable, or left undefined for things like Rust arrays where they are not. It is also implemented for movements (
]
and[
).I've implemented the queries for a number of core languages, but note that deciding on whether something gets to be considered a data structure can be subjective. In particular, some languages encourage data structures implemented as classes where the properties are the entries/elements. However, because it's unclear how methods should interact with this feature, I chose the conservative path and did not implement the queries for classes in the languages that have such a concept. I suspect that native users of each language will want to evolve what is considered a data structure like entry over time.
This feature also introduces textobjects for a number of languages that did not have textobjects defined at all before, such as JSON and TOML, where no other query type makes sense.